package com.waypolice.manager.controller;

import com.waypolice.base.BaseController;
import com.waypolice.common.utils.MD5Util;
import com.waypolice.manager.service.*;
import com.waypolice.manager.session.UpmsSession;
import com.waypolice.pojo.UpmsOrganization;
import com.waypolice.pojo.UpmsUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections4.map.HashedMap;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;


/**
 * @Description 登录和退出Action
 * @Author wangrang
 * @Date Created in 10:53 2019/1/2
 * @Modified By:
 */
@Controller
@Api(value = "登录和退出Action", description = "登录和退出Action")
public class LoginAndLogoutAction extends BaseController {
    private static final Logger logger = LoggerFactory.getLogger(LoginAndLogoutAction.class);

    @Autowired
    private MainMenuService mainmenuservice;

    @Autowired
    private UpmsApiService upmsApiService;

    @Autowired
    private SessionDAO sessionDAO;

    @Autowired
    private UpmsUserService upmsUserService;

    @Autowired
    private UpmsOrganizationService upmsorganizationservice;

    @Autowired
    private FirstHomeService firstHomeService;

    /**
     * 登录页面跳转(从WEB-INF外部的index页面跳转至login页面)
     * @return
     */
    @ApiOperation(value = "登录页面跳转")
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ModelAndView indexLogin(String error) {
        ModelAndView model=new ModelAndView("login");
        if(null==error){
            model.addObject("msg","");
        }else if(MD5Util.md5(String.valueOf(1)+"error".toString()).equals(error)){
            model.addObject("msg",MD5Util.md5(String.valueOf(1)+"error".toString()));//账号不存在60EB894B8E11B6497D101967CEE4C62E
        }else if(MD5Util.md5(String.valueOf(2)+"error".toString()).equals(error)){
            model.addObject("msg",MD5Util.md5(String.valueOf(2)+"error".toString()));//密码错误C44DC417D152077E9FF976C711AC0566
        }else if(MD5Util.md5(String.valueOf(3)+"error".toString()).equals(error)){
            model.addObject("msg",MD5Util.md5(String.valueOf(3)+"error".toString()));//账号已锁定38D90CE7FA3DB1125366B4D8817689F5
        }else if(MD5Util.md5(String.valueOf(4)+"error".toString()).equals(error)){
            model.addObject("msg",MD5Util.md5(String.valueOf(4)+"error".toString()));//未登录验证8530D3D5D3CF2E3B78B9AA30C6432B50
        }else if(MD5Util.md5(String.valueOf(5)+"error".toString()).equals(error)){
            model.addObject("msg",MD5Util.md5(String.valueOf(5)+"error".toString()));//同一浏览器多账号登陆7AB519479FC31FACD3B76FE51437BE7B
        }
        return model;
    }


    @ApiOperation(value = "用户登录操作")
    @RequestMapping(value = "/loginuser",method=RequestMethod.GET)
    public String loginGet( HttpServletResponse response, HttpServletRequest request) throws Exception{
        //用户刷新url，判断用户是否已登录，如果已经登录则跳转回首页，如果验证未通过则销毁session并跳转回登录页面
        Subject subject = SecurityUtils.getSubject();
        boolean authenticated = subject.isAuthenticated();
        if(authenticated){
            Map<String,Object> objMap = new HashedMap<String, Object>();
            UpmsUser newuser = upmsApiService.selectUpmsUserByUsername((String) subject.getPrincipal());
            List<Map<String, Object>> mainMenu = mainmenuservice.getMainMenu(newuser.getUserId());
            objMap.put("user", newuser);
            request.setAttribute("objMap", objMap);
            request.setAttribute("mainMenu",mainMenu);
            return "/main";
        }else{
            subject.logout();
            return "redirect:/login?error="+MD5Util.md5(String.valueOf(4)+"error".toString());
        }
    }

    /**
     * 用户登录操作
     *
     * @param
     * @param response
     * @param request
     * @return
     * @throws Exception
     */
    @ApiOperation(value = "用户登录操作")
    @RequestMapping(value = "/loginuser" ,method=RequestMethod.POST)
    public String loginPost(UpmsUser upmsUser, HttpServletResponse response, HttpServletRequest request) throws Exception  {
        request.setCharacterEncoding("utf-8");
        String username = upmsUser.getUsername();
        String password = upmsUser.getPassword();
        Subject subject = SecurityUtils.getSubject();
        Collection<Session> sessions = sessionDAO.getActiveSessions();
        if(sessions.size()>0){
            for(Session x:sessions){
                Collection<Object> attributeKeys = x.getAttributeKeys();
                if(attributeKeys.size()>0){
                    //不同账户在同一浏览器登录，因为sessionId相同，所以会造成权限混乱，需进行限制
                    if(null!=x.getAttribute("sessionId")
                            &&null!=x.getAttribute("loginName")
                            &&!x.getAttribute("loginName").equals(username)
                            &&x.getAttribute("sessionId").equals(subject.getSession().getId().toString())){
                        return "redirect:/login?error="+MD5Util.md5(String.valueOf(5)+"error".toString());
                    }else if(null!=x.getAttribute("loginName")
                            &&null!=x.getAttribute("loginUser")
                            &&x.getAttribute("loginName").equals(username)
                            &&!x.getAttribute("sessionId").equals(subject.getSession().getId().toString())
                            ){
                        UpmsUser onLineUser = (UpmsUser)x.getAttribute("loginUser");
                        if(onLineUser.getPassword().equals(MD5Util.md5(password + onLineUser.getSalt()))){
                            //同一账号在不同浏览器登陆，踢掉在线用户(或是上次异常退出时未处理session会话，本次登陆主动删除上次的无用会话)
                            sessionDAO.delete(x);
                        }
                    }
                }

            }
        }
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
        try {
                subject.login(token);
            } catch (UnknownAccountException e) {
                //1账号不存在
                return "redirect:/login?error="+MD5Util.md5(String.valueOf(1)+"error".toString());
            } catch (IncorrectCredentialsException e) {
                //密码错误
                return "redirect:/login?error="+MD5Util.md5(String.valueOf(2)+"error".toString());
            } catch (LockedAccountException e) {
                //帐号已锁定
                return "redirect:/login?error="+MD5Util.md5(String.valueOf(3)+"error".toString());
            }
        Map<String,Object> objMap = new HashedMap<String, Object>();
        UpmsUser newuser = upmsApiService.selectUpmsUserByUsername(username);
        List<Map<String, Object>> mainMenu = mainmenuservice.getMainMenu(newuser.getUserId());
        List<UpmsOrganization> organization = upmsorganizationservice.getOrganization(newuser.getUserId());
        if(null!=organization&&organization.size()>0){
            objMap.put("organization",organization.get(0).getName());
        }else{
            objMap.put("organization","无组织机构");
        }
        objMap.put("user", newuser);
        request.setAttribute("objMap", objMap);
        request.setAttribute("mainMenu",mainMenu);
        // 登录成功，将用户和用户名、sessionId放入session，跳转至成功登陆页
        subject.getSession().setAttribute("loginName",newuser.getUsername());
        subject.getSession().setAttribute("loginUser",newuser);
        subject.getSession().setAttribute("sessionId",subject.getSession().getId().toString());
        return "/main";
    }

    /**
     * 进入修改密码
     *
     * @param request
     * @param response
     * @return
     */
    @ApiOperation(value = "进入修改密码操作")
    @RequestMapping(value = "/pcwindow/modifiedPassword")
    public String moPasswordJump(HttpSession session, HttpServletRequest request,
                                 HttpServletResponse response, SessionStatus sessionStatus) {
        return "/userManager/editPassword";
    }

    /**
     * 退出密码修改页面
     *
     * @param request
     * @param response
     * @return
     */
    @ApiOperation(value = "进入修改密码操作")
    @RequestMapping(value = "/pcwindow/modifiedPasswordOut")
    public String passwordOutJump(HttpSession session, HttpServletRequest request,
                                 HttpServletResponse response, SessionStatus sessionStatus) {
        Map<String, String> countData = firstHomeService.homePageAllCountData();
        request.setAttribute("countData",countData);
        return "/dashboard";
    }

    /**
     * 用户修改密码验证步骤
     *
     * @param passWord
     *
     * @return
     */
    @ApiOperation(value = "密码验证")
    @RequestMapping(value = "/pcwindow/verifyPassword",method = RequestMethod.POST)
    @ResponseBody
    public String passWordVerify(String passWord) {
        String flag="0";
        Subject subject=SecurityUtils.getSubject();
        UpmsUser user = (UpmsUser)subject.getSession().getAttribute("loginUser");
        if(user.getPassword().equals(MD5Util.md5(passWord + user.getSalt()))){
            flag="1";
        }
        return flag;
    }


    /**
     * 密码修改
     *
     * @param newPassword
     *
     * @return
     */
    @ApiOperation(value = "密码修改")
    @RequestMapping(value = "/pcwindow/newPassword",method = RequestMethod.POST)
    @ResponseBody
    public String updateNewWord(String newPassword) {
        String flag="0";
        Subject subject=SecurityUtils.getSubject();
        UpmsUser user = (UpmsUser)subject.getSession().getAttribute("loginUser");
        String salt = UUID.randomUUID().toString().replaceAll("-", "");
        user.setSalt(salt);
        user.setPassword(MD5Util.md5(newPassword + salt));
        int i = upmsUserService.updateByPrimaryKey(user);
        return String.valueOf(i);
    }

    /**
     * 用户退出跳转
     *
     * @param request
     * @param response
     * @return
     */
    @ApiOperation(value = "用户退出跳转")
    @RequestMapping(value = "/pcwindow/logout")
    public String logoutJump(HttpSession session, HttpServletRequest request,
                             HttpServletResponse response, SessionStatus sessionStatus) {
        return "/userManager/logout";
    }
    /**
     * 用户退出操作
     * @param request
     * @param response
     * @return
     */
    @ApiOperation(value = "用户退出操作")
    @RequestMapping(value = "/pcwindow/logoutSystemJump")
    @ResponseBody
    public String logoutSystemJump(HttpSession session, HttpServletRequest request,
                                   HttpServletResponse response, SessionStatus sessionStatus) {
        String flag="0";
        Subject subject = SecurityUtils.getSubject();
        boolean authenticated = subject.isAuthenticated();
        if(authenticated){
            SecurityUtils.getSubject().logout();
            flag="1";
        }
        return flag;
    }

    @ApiOperation(value = "用户关闭浏览器操作")
    @RequestMapping(value = "/pcwindow/destroySession", method=RequestMethod.GET)
    public void destroySession( HttpServletRequest request,HttpServletResponse response) {
        Subject subject = SecurityUtils.getSubject();
        boolean authenticated = subject.isAuthenticated();
        if(authenticated){
            SecurityUtils.getSubject().logout();
        }
    }

}
